package com.power.project.service.impl;

import cn.hutool.core.lang.tree.Tree;
import com.power.base.service.impl.BaseServiceImpl;
import com.power.project.dao.Ha_manageDao;
import com.power.project.dao.Ww_depart_userDao;
import com.power.project.dao.Ww_userDao;
import com.power.project.dao.Ww_usertagDao;
import com.power.project.model.*;
import com.power.project.model.bo.UserRemoveBO;
import com.power.project.model.bo.UserSaveBO;
import com.power.project.model.dto.UserDTO;
import com.power.project.model.dto.UserDepartDTO;
import com.power.project.model.dto.UserTagDTO;
import com.power.project.model.pageInfo.UserQueryPageInfo;
import com.power.project.model.vo.DepartUserVO;
import com.power.project.model.vo.PasswordVO;
import com.power.project.model.vo.UserBaseVO;
import com.power.project.model.vo.UserDetailVO;
import com.power.project.service.Ww_departService;
import com.power.project.service.Ww_userService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 业务层实现
 */
@Service
public class Ww_userServiceImpl extends BaseServiceImpl implements Ww_userService {

    @Resource
    private Ww_userDao dao;

    @Autowired
    private Ww_departService departService;

    @Autowired
    private Ww_depart_userDao departUserDao;

    @Autowired
    private Ww_usertagDao userTagDao;

    @Autowired
    private AccountServiceImpl accountService;

    @Autowired
    private Ha_manageDao manageDao;

    @Override
    public Page<DepartUserVO> findAll(UserQueryPageInfo pageInfo) {
        List<Tree<String>> trees = departService.tree(pageInfo.getTenantId());

        Pageable pageable = PageRequest.of(pageInfo.getPageNumber() <= 1 ? 0 : pageInfo.getPageNumber() - 1, pageInfo.getPageSize());

        Page<UserDTO> page = dao.findAll(pageInfo, pageable);
        List<UserDTO> list = page.getContent();

        List<String> userIds = list.stream().map(Ww_user::getUserid).collect(Collectors.toList());

        List<UserTagDTO> tags = userTagDao.getByUserIds(userIds, pageInfo.getTenantId());
        List<UserDepartDTO> departs = departUserDao.getByUserIds(userIds, pageInfo.getTenantId());
        List<String> manageUserIds =  manageDao.findUseridByUseridIn(userIds);
        Map<String, List<UserTagDTO>> tagMapList = tags.stream().collect(Collectors.groupingBy(UserTagDTO::getUserId));
        Map<String, List<UserDepartDTO>> departMapList = departs.stream().collect(Collectors.groupingBy(UserDepartDTO::getUserId));

        List<DepartUserVO> resultList = new ArrayList<>();

        for (UserDTO dto : list) {
            DepartUserVO vo = new DepartUserVO(dto);
            List<UserDepartDTO> userDeparts = departMapList.get(dto.getUserid());
            vo.setDepartments(trees, userDeparts);
            List<UserTagDTO> tmpUserTags = tagMapList.get(dto.getUserid());
            if (!CollectionUtils.isEmpty(tmpUserTags)) {
                vo.setTags(tmpUserTags.stream().map(UserTagDTO::getName).collect(Collectors.joining(",")));
            }
            if(!CollectionUtils.isEmpty(manageUserIds) && manageUserIds.contains(dto.getUserid())){
                vo.setIsOwner(true);
            }
            resultList.add(vo);
        }

        return new PageImpl<>(resultList, page.getPageable(), page.getTotalElements());
    }

    @Override
    public Page<DepartUserVO> findAllByDepart(UserQueryPageInfo pageInfo) {

        List<Tree<String>> trees = departService.tree(pageInfo.getTenantId());

        Pageable pageable = PageRequest.of(pageInfo.getPageNumber() <= 1 ? 0 : pageInfo.getPageNumber() - 1, pageInfo.getPageSize());

        Page<UserDTO> page = dao.findAll(pageInfo, pageable);
        List<UserDTO> list = page.getContent();

        List<String> userIds = list.stream().map(Ww_user::getUserid).collect(Collectors.toList());

        List<UserTagDTO> tags = userTagDao.getByUserIds(userIds, pageInfo.getTenantId());
        List<UserDepartDTO> departs = departUserDao.getByUserIds(userIds, pageInfo.getTenantId());

        Map<String, List<UserTagDTO>> tagMapList = tags.stream().collect(Collectors.groupingBy(UserTagDTO::getUserId));
        Map<String, List<UserDepartDTO>> departMapList = departs.stream().collect(Collectors.groupingBy(UserDepartDTO::getUserId));

        List<DepartUserVO> resultList = new ArrayList<>();

        for (UserDTO dto : list) {
            DepartUserVO vo = new DepartUserVO(dto);
            List<UserDepartDTO> userDeparts = departMapList.get(dto.getUserid());
            vo.setDepartments(trees, userDeparts);
            List<UserTagDTO> tmpUserTags = tagMapList.get(dto.getUserid());
            if (!CollectionUtils.isEmpty(tmpUserTags)) {
                vo.setTags(tmpUserTags.stream().map(UserTagDTO::getName).collect(Collectors.joining(",")));
            }
            vo.setIsLeader(userDeparts, pageInfo.getDepartmentId());
            resultList.add(vo);
        }

        return new PageImpl<>(resultList, page.getPageable(), page.getTotalElements());
    }

    @Override
    public Page<UserBaseVO> findAllByTag(UserQueryPageInfo pageInfo) {

        List<Tree<String>> trees = departService.tree(pageInfo.getTenantId());

        Pageable pageable = PageRequest.of(pageInfo.getPageNumber() <= 1 ? 0 : pageInfo.getPageNumber() - 1, pageInfo.getPageSize());

        Page<UserDTO> page = dao.findAll(pageInfo, pageable);
        List<UserDTO> list = page.getContent();

        List<String> userIds = list.stream().map(Ww_user::getUserid).collect(Collectors.toList());

        List<UserDepartDTO> departs = departUserDao.getByUserIds(userIds, pageInfo.getTenantId());

        Map<String, List<UserDepartDTO>> departMapList = departs.stream().collect(Collectors.groupingBy(UserDepartDTO::getUserId));

        List<UserBaseVO> resultList = new ArrayList<>();

        for (UserDTO dto : list) {
            UserBaseVO vo = new UserBaseVO(dto);
            List<UserDepartDTO> userDeparts = departMapList.get(dto.getUserid());
            vo.setDepartments(trees, userDeparts);
            resultList.add(vo);
        }

        return new PageImpl<>(resultList, page.getPageable(), page.getTotalElements());
    }

    @Override
    public Ww_user getByUserId(String userid) {
        return dao.getByUserId(userid);
    }

    @Override
    public PasswordVO queryUserPassword(String userid) {
        List<PasswordVO> list = this.dao.queryUserPassword(userid);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<Ww_user> findByTenantidAndUseridIn(String tenantid, List<String> userIdList) {
        return dao.findByTenantidAndUseridIn(tenantid, userIdList);
    }

    @Override
    public UserDetailVO view(String userId) {
        Ww_user user = dao.getByUserId(userId);
        List<UserDepartDTO> departList = departUserDao.getByUserIds(Collections.singletonList(userId), user.getTenantid());
        List<UserTagDTO> tagList = userTagDao.getByUserIds(Collections.singletonList(userId), user.getTenantid());

        UserDetailVO vo = new UserDetailVO(user);
        vo.setDepartList(departList);
        vo.setTagList(tagList);
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(UserSaveBO saveBO) {
        Ww_user user = dao.getByUserId(saveBO.getUserId());
        if (user != null) {
            user.setSaveBO(saveBO);
        } else {
            user = new Ww_user(saveBO);
            accountService.addUser(saveBO.getUserId(), saveBO.getPassword());
        }
        dao.save(user);
        Ww_user finalUser = user;
        // 2024/7/3 删除标签、重新增加标签
        userTagDao.deleteByUserIdAndTenantId(user.getUserid(), user.getTenantid());
        if (!CollectionUtils.isEmpty(saveBO.getTagList())) {
            List<Ww_usertag> tags = saveBO.getTagList().stream().map(t -> new Ww_usertag(t, finalUser.getUserid(), finalUser.getTenantid())).collect(Collectors.toList());
            userTagDao.saveAll(tags);
        }

        // 2024/7/3 删除部门、重新增加部门
        // 查看用户原负责部门列表
        List<Ww_depart> tmpList = departService.getLeadDepartment(user.getUserid(), user.getTenantid());
        List<String> tmpIdList = tmpList.stream().map(Ww_depart::getDepartid).collect(Collectors.toList());
        // 新增的负责的部门id
        List<String> addList = new ArrayList<>();
        // 移除的负责的部门id
        List<String> removeList = new ArrayList<>();
        departUserDao.deleteByUserIdAndTenantId(user.getUserid(), user.getTenantid());
        if (!CollectionUtils.isEmpty(saveBO.getDepartList())) {
            List<String> saveLeaderIdList = saveBO.getDepartList()
                    .stream()
                    .filter(t -> Integer.valueOf(1).equals(t.getIsLeader()))
                    .map(UserDepartDTO::getDepartId)
                    .collect(Collectors.toList());
            List<Ww_depart_user> tags = saveBO.getDepartList().stream().map(t -> new Ww_depart_user(t, finalUser.getUserid(), finalUser.getTenantid())).collect(Collectors.toList());
            departUserDao.saveAllAndFlush(tags);
            addList = saveLeaderIdList.stream().filter(t -> !tmpIdList.contains(t)).collect(Collectors.toList());
            removeList = tmpIdList.stream().filter(t -> !saveLeaderIdList.contains(t)).collect(Collectors.toList());
        } else {
            removeList = tmpIdList;
        }
        addList.addAll(removeList);
        if (!CollectionUtils.isEmpty(addList)) {
            departService.resetLeaders(addList, user.getTenantid());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchRemove(UserRemoveBO removeBO) {
        Ww_depart depart = departService.getByDepartId(removeBO.getDepartId());

        departUserDao.removeByDepartIdAndUserIds(depart.getDepartid(), removeBO.getUserIds(), depart.getTenantid());

        departService.resetLeaders(Collections.singletonList(depart.getDepartid()), depart.getTenantid());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByUserId(String userId) {
        Ww_user user = dao.getByUserId(userId);

        List<Ww_depart> tmpList = departService.getLeadDepartment(user.getUserid(), user.getTenantid());
        List<String> tmpIdList = tmpList.stream().map(Ww_depart::getDepartid).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(tmpIdList)) {
            departService.resetLeaders(tmpIdList, user.getTenantid());
        }

        dao.deleteByUserId(userId);
    }

    @Override
    public List<Ww_user> findByUseridIn(List<String> userIds) {
        return dao.findByUseridIn(userIds);
    }
}
